-
Notifications
You must be signed in to change notification settings - Fork 524
Fixing rounding errors when inserting microseconds #407
Conversation
When calculating nanoseconds since EPOCH, `total_seconds()` will give a float representation which when multiplied by 1e9 and cast to `int` will create rounding errors. E.g. inserting `2017-01-17T08:00:12.000001` with a datetime will produce `2017-01-17T08:00:12.000001024Z` in InfluxDB. This commit fixes this by never going via floating seconds, and is based on the `total_seconds()` function itself.
influxdb/line_protocol.py
Outdated
@@ -16,6 +16,12 @@ | |||
EPOCH = UTC.localize(datetime.utcfromtimestamp(0)) | |||
|
|||
|
|||
def _to_nanos(timestamp): | |||
delta = timestamp - EPOCH | |||
nanos = (delta.days * 86400 + delta.seconds) * 10 ** 9 + delta.microseconds * 10 ** 3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this line fails flake8 (89 chars), mind splitting it up? otherwise, this looks like a good change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The `_to_nanos` function had a line which was too long.
Just encountered this rounding error and was about to submit this very patch. In order to ensure that ns stays an int I would also rewrite: if precision is None or precision == 'n':
return ns
elif precision == 'u':
return ns / 1e3
elif precision == 'ms':
return ns / 1e6
elif precision == 's':
return ns / 1e9
elif precision == 'm':
return ns / 1e9 / 60
elif precision == 'h':
return ns / 1e9 / 3600 to if precision is None or precision == 'n':
return ns
elif precision == 'u':
return ns / 10**3
elif precision == 'ms':
return ns / 10**6
elif precision == 's':
return ns / 10**9
elif precision == 'm':
return ns / 10**9 / 60
elif precision == 'h':
return ns / 10**9 / 3600 |
It would probably allow you to close some of those: |
Re-addressed in a new PR that merges this content including fixes from @clslgrnc |
When calculating nanoseconds since EPOCH,
total_seconds()
will give a float representation which when multiplied by 1e9 and cast toint
will create rounding errors. E.g. inserting2017-01-17T08:00:12.000001
with a datetime will produce2017-01-17T08:00:12.000001024Z
in InfluxDB. This commit fixes this by never going via floating seconds, and is based on thetotal_seconds()
function itself.